package edu.gatech.spacetraderteam3.view;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import edu.gatech.spacetraderteam3.controller.GUIEventHandler;
import edu.gatech.spacetraderteam3.model.GameState;
import edu.gatech.spacetraderteam3.model.Resource;
import edu.gatech.spacetraderteam3.model.ShipArmor;
import edu.gatech.spacetraderteam3.model.ShipShield;
import edu.gatech.spacetraderteam3.model.ShipWeapon;
import edu.gatech.spacetraderteam3.model.SpacePlanet.PlanetPaintDelegate;

/**
 * The GUI representation of a planet
 * 
 * @author Alexander Ikonomidis and Ashutosh Gupta
 * @version 1.0
 */
public class ViewPlanet extends View {

    /**
     * The welcome dialog box that pops up upon landing
     */
    private final SGGWindow welcomeDialog;

    /**
     * A welcome label for the dialog box
     */
    private SGGLabel welcomeLabel;

    /**
     * A boolean value to show whether this is a first visit
     */
    private boolean firstArrival = true;

    /**
     * The player's inventory
     */
    private Map<Resource, Integer> playerAmount;

    /**
     * The panel of buttons for different pop up windows
     */
    private final SGGWindow buttonPanel;

    /**
     * Paints the planet
     */
    private PlanetPaintDelegate paintDelegate;

    // Ship Info Dialog
    /**
     * Shows the ships information
     */
    private final SGGWindow shipInfoDialog;

    /**
     * Shows your current cash
     */
    private final SGGLabel shipInfoCashLabel;

    /**
     * Shows your name
     */
    private final SGGLabel shipInfoNameLabel;

    /**
     * Shows your ship's type
     */
    private final SGGLabel shipInfoTypeLabel;

    /**
     * Shows the amount of fuel you have
     */
    private final SGGLabel shipInfoFuelLabel;

    /**
     * Shows the type of shield you have
     */
    private final SGGLabel shipInfoShieldLabel;

    /**
     * shows the type of weapon you have
     */
    private final SGGLabel shipInfoWeaponLabel;

    /**
     * shows the type of armor you have
     */
    private final SGGLabel shipInfoArmorLabel;
    
    /**
     * Shows max cargo weight 
     */
    
    private final SGGLabel shipInfoCargoLabel;

    /**
     * Shows cost of refueling
     */
    private final SGGLabel shipInfoFuelUpLabel;

    /**
     * Shows cost of upgrading
     */
    private final SGGLabel shipInfoShieldUpLabel;

    /**
     * Shows cost of upgrading
     */
    private final SGGLabel shipInfoWeaponUpLabel;

    /**
     * Shows cost of upgrading
     */
    private final SGGLabel shipInfoArmorUpLabel;
    
    /**
     * Shos cost of upgrading
     */
    
    private final SGGLabel shipInfoCargoUpLabel;

    /**
     * Fires refuel event
     */
    private final SGGButton refillButton;

    /**
     * Fires upgrade shield event
     */
    private final SGGButton upgradeShield;

    /**
     * Fires upgrade weapon event
     */
    private final SGGButton upgradeWeapon;

    /**
     * Fires upgrade armor event
     */
    private final SGGButton upgradeArmor;
    
    /**
     * fires upgrade cargo weight even
     */
    
    private final SGGButton upgradeCargoWeight;

    // Cargo Dialog
    /**
     * Shows the cargo of a ship
     */
    private SGGWindow cargoDialog;

    /**
     * Displays the resources and the amount in the cargo
     */
    private final SGGLabel[] cargoLabels;

    private SGGWindow newsDialog;

    private SGGLabel news;

    /**
     * Constcutor for the planet view
     */
    public ViewPlanet() {
        playerAmount = new HashMap<Resource, Integer>();
        shipInfoCashLabel = new SGGLabel("Cash: $0");
        shipInfoNameLabel = new SGGLabel("Name: ");
        shipInfoTypeLabel = new SGGLabel("Type: ");
        shipInfoFuelLabel = new SGGLabel("Fuel: ");
        shipInfoShieldLabel = new SGGLabel("Shield: ");
        shipInfoWeaponLabel = new SGGLabel("Weapon: ");
        shipInfoArmorLabel = new SGGLabel("Armor: ");
        shipInfoCargoLabel = new SGGLabel("Max Cargo Weight: ");
        shipInfoFuelUpLabel = new SGGLabel("Refuel Price: $0");
        shipInfoShieldUpLabel = new SGGLabel("Upgarde: $0");
        shipInfoWeaponUpLabel = new SGGLabel("Upgarde: $0");
        shipInfoArmorUpLabel = new SGGLabel("Upgarde: $0");
        shipInfoCargoUpLabel = new SGGLabel("Upgrade: $0");
        refillButton = new SGGButton("Refuel");
        upgradeShield = new SGGButton("Upgrade");
        upgradeWeapon = new SGGButton("Upgrade");
        upgradeArmor = new SGGButton("Upgrade");
        upgradeCargoWeight = new SGGButton("Upgrade");
        cargoLabels = new SGGLabel[20];// playerAmount.keySet().size()];
        news = new SGGLabel("News");
        news.setLineWidth(55);

        welcomeDialog = buildWelcomeDialog();
        shipInfoDialog = buildShipInfoDialog();
        cargoDialog = buildCargoDialog();
        buttonPanel = buildButtonPanel();
        newsDialog = buildNewsDialog();

        PopupWindows = new ArrayList<SGGWindow>();
        PopupWindows.add(welcomeDialog);
        PopupWindows.add(shipInfoDialog);
    }

    /**
     * @return a newly built welcome dialog
     */
    public SGGWindow buildWelcomeDialog() {
        final SGGWindow window = new SGGWindow(0, 0, 300, 200, GameState.PLANET);
        window.setAlignment(SGGWindow.Alignment.CENTER);
        welcomeLabel = new SGGLabel("Welcome to space trader! <game info goes here>");
        welcomeLabel.setLineWidth(35);
        window.add(welcomeLabel, 30, 50);
        window.add(new SGGButton("Go!") {
            {
                setSGGEventListener(new SGGEventListener() {
                    public void doEvent(SGGEvent sgge) {
                        closeWelcomeMessage();
                    }
                });
            }
        }, 175, 120);
        return window;
    }

    /**
     * @return a newly built ship information dialog
     */
    public SGGWindow buildShipInfoDialog() {
        final SGGWindow window = new SGGWindow(0, 160, 390, 345, GameState.PLANET);
        refillButton.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.refuel();
            }
        });
        upgradeShield.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.upgradeShield();
            }
        });
        upgradeWeapon.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.upgradeWeapon();
            }
        });
        upgradeArmor.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.upgradeArmor();
            }
        });
        upgradeCargoWeight.setSGGEventListener(new SGGEventListener(){
            public void doEvent(SGGEvent sgge){
                GUIEventHandler.upgradeCargo();
            }
        });

        window.add(shipInfoNameLabel, 30, 30);
        window.add(shipInfoTypeLabel, 30, 50);
        window.add(shipInfoCashLabel, 30, 70);
        window.add(shipInfoFuelLabel, 30, 90);
        window.add(shipInfoFuelUpLabel, 35, 105);
        window.add(shipInfoShieldLabel, 30, 135);
        window.add(shipInfoShieldUpLabel, 35, 150);
        window.add(shipInfoWeaponLabel, 30, 180);
        window.add(shipInfoWeaponUpLabel, 35, 195);
        window.add(shipInfoArmorLabel, 30, 225);
        window.add(shipInfoArmorUpLabel, 35, 240);
        window.add(shipInfoCargoLabel, 30, 270);
        window.add(shipInfoCargoUpLabel, 35, 285);
        window.add(refillButton, 240, 90);
        window.add(upgradeShield, 240, 135);
        window.add(upgradeWeapon, 240, 180);
        window.add(upgradeArmor, 240, 225);
        window.add(upgradeCargoWeight, 240, 270);
        window.hasPoint(true);
        window.setPointSide(SGGComponent.Direction.SOUTH);
        window.setPointOffset(-138);
        window.setAlignment(SGGWindow.Alignment.BOTTOM_LEFT);
        window.setVisible(false);
        return window;
    }

    /**
     * 
     * @return a newly built cargo info dialog
     */
    public SGGWindow buildCargoDialog() {
        final SGGWindow window = new SGGWindow(103, 160, 155, 300, GameState.PLANET);
        final SGGLabel cargoTitleLabel = new SGGLabel("Ship Cargo: ");

        int i = 0;
        for (Resource r : playerAmount.keySet()) {
            cargoLabels[i] = new SGGLabel(r + "     " + playerAmount.get(r));
            window.add(cargoLabels[i], 30, 60 + 20 * i);
            i++;
        }

        window.add(cargoTitleLabel, 30, 30);
        window.hasPoint(true);
        window.setPointSide(SGGComponent.Direction.SOUTH);
        window.setPointOffset(-7);
        window.setAlignment(SGGWindow.Alignment.BOTTOM_LEFT);
        window.setVisible(false);
        return window;
    }

    public SGGWindow buildNewsDialog() {
        final SGGWindow window = new SGGWindow(270, 160, 390, 300, GameState.PLANET);

        window.add(news, 30, 30);
        window.hasPoint(true);
        window.setPointSide(SGGComponent.Direction.SOUTH);
        window.setPointOffset(-60);
        window.setAlignment(SGGWindow.Alignment.BOTTOM_LEFT);
        window.setVisible(false);
        return window;
    }

    /**
     * @return a panel with all the main menu buttons
     */
    public SGGWindow buildButtonPanel() {
        final SGGWindow window = new SGGWindow(0, 0, 480, 130, GameState.PLANET);
        window.setAlignment(SGGWindow.Alignment.BOTTOM_LEFT);
        SGGButton button = new SGGButton(Assets.ButtonType.MY_SHIP);
        button.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                togglePopup(shipInfoDialog);
            }
        });
        window.add(button, 8, 8);

        button = new SGGButton(Assets.ButtonType.CARGO);
        button.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                togglePopup(cargoDialog);
            }
        });
        window.add(button, 125, 8);

        button = new SGGButton(Assets.ButtonType.MAP);
        button.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.mapTabPressed();
            }
        });
        window.add(button, 242, 8);

        button = new SGGButton(Assets.ButtonType.NEWS);
        button.setSGGEventListener(new SGGEventListener() {
            public void doEvent(SGGEvent sgge) {
                GUIEventHandler.newsTabPressed();
                togglePopup(newsDialog);
            }
        });
        window.add(button, 359, 8);
        return window;
    }

    /**
     * Hides the welcome message
     */
    private void closeWelcomeMessage() {
        welcomeDialog.setVisible(false);
        // buySellPanel.setFocusable(true);
        buttonPanel.setFocusable(true);
    }

    /**
     * Sets the welcome message text
     * 
     * @param message
     */
    public void setWelcomeMessage(String message) {
        welcomeLabel.setText(message);
    }

    /**
     * sets this planet's paint delegate
     * 
     * @param paintDelegate
     */
    public void setPlanetPaintDelegate(PlanetPaintDelegate paintDelegate) {
        this.paintDelegate = paintDelegate;
    }

    /**
     * Sets the amount of cash the player has
     * 
     * @param credits
     */
    public void setCredits(int credits) {
        shipInfoCashLabel.setText("Cash: $" + credits);
    }

    /**
     * sets the inventory of the player
     * 
     * @param map
     */
    public void setPlayerAmount(Map<Resource, Integer> map) {
        this.playerAmount = map;
        int i = 0;
        for (Resource r : map.keySet()) {
            if (cargoLabels[i] == null) {
                cargoLabels[i] = new SGGLabel("");
            }
            cargoLabels[i].setText(r + "     " + map.get(r));
            i++;
        }
    }

    /**
     * initializes the ships info labels
     * 
     * @param name
     * @param type
     * @param resource
     * @param prices
     */
    public void setShipInfo(String name, String type, int[] resource, int[] prices) {
        shipInfoNameLabel.setText("Name: " + name);
        shipInfoTypeLabel.setText("Type: " + type);
        shipInfoFuelLabel.setText("Fuel: " + resource[0]);

        shipInfoFuelUpLabel.setText("Refuel Price: $" + prices[0]);
        shipInfoShieldUpLabel.setText("Upgrade: $" + prices[1]);
        shipInfoWeaponUpLabel.setText("Upgrade: $" + prices[2]);
        shipInfoArmorUpLabel.setText("Upgrade: $" + prices[3]);
        shipInfoCargoUpLabel.setText("Upgrade: $" + prices[4]);

        shipInfoShieldLabel.setText("Shield: " + ShipShield.getShieldName(resource[1]));
        shipInfoWeaponLabel.setText("Weapon: " + ShipWeapon.getWeaponName(resource[2]));
        shipInfoArmorLabel.setText("Armor: " + ShipArmor.getArmorName(resource[3]));
        shipInfoCargoLabel.setText("Max Cargo Weight: " + resource[4]);
    }

    /**
     * Paints the ship onto the screen
     * 
     * @param g2
     *            graphics object
     */
    public void paint(Graphics2D g2) {
        super.paint(g2);
        if (paintDelegate != null) {
            final BufferedImage tile = paintDelegate.getTile().image();// TODO: support
                                                                       // more tiles
            for (int x = 0; x <= wid; x += tile.getWidth()) {
                for (int y = 0; y <= hei; y += tile.getHeight()) {
                    g2.drawImage(tile, x, y, null);
                }
            }
            final BufferedImage planetBack = paintDelegate.getSurface().image();
            g2.drawImage(planetBack, centerX - planetBack.getWidth() / 2, centerY
                    - planetBack.getHeight() / 2, null);

            buttonPanel.paint(g2);
            shipInfoDialog.paint(g2);
            cargoDialog.paint(g2);
            welcomeDialog.paint(g2);
            newsDialog.paint(g2);
        }
    }

    /**
     * Initializes the player's information
     * 
     * @param pricesAndWeights
     * @param cargoWeight
     */
    public void initialize(Map<Resource, int[]> pricesAndWeights, int cargoWeight,
            String news) { // buyPrice, sellPrice, weight
        if (cargoDialog != null) {
            cargoDialog.dispose();
        }
        PopupWindows.remove(cargoDialog);
        cargoDialog = buildCargoDialog();
        PopupWindows.add(cargoDialog);

        if (newsDialog != null) {
            newsDialog.dispose();
        }
        PopupWindows.remove(newsDialog);
        this.news.setText(news);
        newsDialog = buildNewsDialog();
        PopupWindows.add(newsDialog);

        hidePopups();

        welcomeDialog.setFocusable(true);
        welcomeDialog.setVisible(true);
        if (firstArrival) {
            welcomeLabel.setText("Welcome to Space Trader!");
            firstArrival = false;
        }
    }

    /**
     * @return Currently viewed planet: + planet
     */
    public String toString() {
        return "Currently viewed planet: " + paintDelegate.toString();
    }
}
